using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Text;
using Microsoft.AspNetCore.Http;
using Infrastructure.Logging;
using ApplicationCore.Interfaces;
using ApplicationCore.Services;
using Infrastructure.Data;
using Infrastructure.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;

namespace Web.Admin
{
	public class Startup
	{
		private IServiceCollection _services;
		public Startup(IConfiguration configuration)
		{
			Configuration = configuration;
		}

		public IConfiguration Configuration { get; }

		public void ConfigureDevelopmentServices(IServiceCollection services)
		{
			// use in-memory database
			//ConfigureTestingServices(services);

			// use real database
			ConfigureProductionServices(services);

		}
		public void ConfigureTestingServices(IServiceCollection services)
		{
			// use in-memory database
			services.AddDbContext<ZBContext>(c =>
				c.UseInMemoryDatabase("zb"));

			// Add Identity DbContext
			services.AddDbContext<AppIdentityDbContext>(options =>
				options.UseInMemoryDatabase("zb.Identity"));

			ConfigureServices(services);
		}

		public void ConfigureProductionServices(IServiceCollection services)
		{
			// use real database
			services.AddDbContext<ZBContext>(c =>
			{
				try
				{
					// Requires LocalDB which can be installed with SQL Server Express 2016
					// https://www.microsoft.com/en-us/download/details.aspx?id=54284
					c.UseSqlServer(Configuration.GetConnectionString("ZBConnection"));
				}
				catch (System.Exception ex)
				{
					var message = ex.Message;
				}
			});

			// Add Identity DbContext
			services.AddDbContext<AppIdentityDbContext>(options =>
				options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection")));

			ConfigureServices(services);
		}

		public void ConfigureServices(IServiceCollection services)
		{
			services.AddIdentity<ApplicationUser, ApplicationRole>()
				.AddEntityFrameworkStores<AppIdentityDbContext>()
				.AddDefaultTokenProviders();

			//services.AddAuthorization(options =>
			//{
			//	options.AddPolicy("",policy=>policy.RequireClaim(""));
			//});


			services.ConfigureApplicationCookie(options =>
			{
				options.Cookie.HttpOnly = true;
				options.ExpireTimeSpan = TimeSpan.FromHours(1);
				options.LoginPath = "/Account/Signin";
				options.LogoutPath = "/Account/Signout";
			});


			services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>));
			services.AddScoped(typeof(IAsyncRepository<>), typeof(EfRepository<>));

			services.AddScoped(typeof(IRoomRepository), typeof(RoomRepository)); 

			services.AddScoped<IChatMsgRepository, ChatMsgRepository>(); 

			services.Configure<ZBSettings>(Configuration);
			services.AddSingleton<IUriComposer>(new UriComposer(Configuration.Get<ZBSettings>()));

			services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));

			// Add memory cache services
			services.AddMemoryCache();

			services.AddMvc();
			 

			_services = services;
		}

		// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
		public void Configure(IApplicationBuilder app,
			IHostingEnvironment env)
		{
			if (env.IsDevelopment())
			{
				app.UseDeveloperExceptionPage();
				app.UseBrowserLink();
				ListAllRegisteredServices(app);
				app.UseDatabaseErrorPage();
			}
			else
			{
				app.UseExceptionHandler("/Home/Error");
			}

			app.UseStaticFiles();
			app.UseAuthentication();
			 
			app.UseMvc(routes =>
			{


				routes.MapRoute(
					name: "default",
					template: "{controller=Home}/{action=Index}/{id?}");




			});
		}

		private void ListAllRegisteredServices(IApplicationBuilder app)
		{
			app.Map("/allservices", builder => builder.Run(async context =>
			{
				var sb = new StringBuilder();
				sb.Append("<h1>All Services</h1>");
				sb.Append("<table><thead>");
				sb.Append("<tr><th>Type</th><th>Lifetime</th><th>Instance</th></tr>");
				sb.Append("</thead><tbody>");
				foreach (var svc in _services)
				{
					sb.Append("<tr>");
					sb.Append($"<td>{svc.ServiceType.FullName}</td>");
					sb.Append($"<td>{svc.Lifetime}</td>");
					sb.Append($"<td>{svc.ImplementationType?.FullName}</td>");
					sb.Append("</tr>");
				}
				sb.Append("</tbody></table>");
				await context.Response.WriteAsync(sb.ToString());
			}));
		}
	}
}
